import {expressjwt} from 'express-jwt'
import {getRedisTokenData} from '../utils/redisClient.js'
import type {Algorithm, Jwt} from 'jsonwebtoken'
import  type {Request, Response, NextFunction} from 'express'

const {JWT_SECRET, JWT_ALGORITHMS, JWT_UNLESS_PATH} = process.env

const unlessPath = JWT_UNLESS_PATH.split(',').map(pattern => new RegExp(pattern))

export function getJwtAuthMiddleware(): {
	(req: Request, res: Response, next: NextFunction): Promise<void>;
	unless: typeof unless;
}{
	return expressjwt({
		secret: JWT_SECRET,
		algorithms: [JWT_ALGORITHMS as Algorithm],
		getToken: function fromHeaderOrQuerystring(req: Request) {
			const headerToken: string | undefined | null = req?.headers?.authorization
			const queryToken = req?.query?.token as string | undefined | null
			const bodyToken: string | undefined | null = req?.body?.token
			return headerToken || queryToken || bodyToken
		},
		isRevoked: async (req: Request, token: Jwt) => {
			const {payload, signature} = token
			const userId = payload ? payload.userId : null
			if(!userId) return true
			const redisToken = await getRedisTokenData(userId) as string
			if(redisToken && redisToken.split('.')[2] === signature) {
				return false
			}else {
				return true
			}
		}
	}).unless({
		path: [
			...unlessPath
		]
	})
}
